#ifndef _GLOBAL_H_
#define _GLOBAL_H_

#include <netinet/in.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "global.h"
#include <pthread.h>
#include <sys/select.h>
#include <arpa/inet.h>

// 调试和trace日志开关
// #define MY_DEBUG
#define MY_TRACE

// 获取当前UTC时间戳（精确到微秒）
extern long getCurrentTime();

// 调试输出文件指针声明
extern FILE* debug_log_file;
extern FILE* trace_log_file;

// 设置调试输出文件
void set_debug_log_file(const char* filename);

// 设置trace日志文件
void set_trace_log_file(const char* filename);

// 关闭调试输出文件
void close_debug_log_file();

// 关闭trace日志文件
void close_trace_log_file();

// 调试信息控制宏
#ifdef MY_DEBUG
// 调试级别定义
#define DEBUG_LEVEL_0 0  // 不输出调试信息
#define DEBUG_LEVEL_1 1  // 输出基本调试信息（状态变化）
#define DEBUG_LEVEL_2 2  // 输出详细调试信息（包处理）
#define DEBUG_LEVEL_3 3  // 输出所有调试信息（包括内部状态）

// 默认调试级别
#ifndef DEBUG_LEVEL
#define DEBUG_LEVEL DEBUG_LEVEL_3
#endif

// 调试信息输出宏 - 重定向到文件
#define DEBUG_LOG(level, format, ...) \
    do { \
        if (DEBUG_LEVEL >= level) { \
            if (debug_log_file != NULL) { \
                fprintf(debug_log_file, "[调试] %s:%d " format "\n", __func__, __LINE__, ##__VA_ARGS__); \
                fflush(debug_log_file); \
            } else { \
                printf("[调试] %s:%d " format "\n", __func__, __LINE__, ##__VA_ARGS__); \
            } \
        } \
    } while (0)

// 特定类型的调试宏
#define DEBUG_STATE(format, ...) DEBUG_LOG(DEBUG_LEVEL_1, "[状态] " format, ##__VA_ARGS__)
#define DEBUG_PACKET(format, ...) DEBUG_LOG(DEBUG_LEVEL_2, "[数据包] " format, ##__VA_ARGS__)
#define DEBUG_DETAIL(format, ...) DEBUG_LOG(DEBUG_LEVEL_3, "[详细] " format, ##__VA_ARGS__)
#else
// 非调试模式下不输出任何调试信息
#define DEBUG_LOG(level, format, ...) do {} while (0)
#define DEBUG_STATE(format, ...) do {} while (0)
#define DEBUG_PACKET(format, ...) do {} while (0)
#define DEBUG_DETAIL(format, ...) do {} while (0)
#endif

// Trace日志宏定义
#ifdef MY_TRACE
#define TRACE_LOG(event, info_format, ...) \
    do { \
        if (trace_log_file != NULL) { \
            fprintf(trace_log_file, "[%ld] [%s] [%s]\n", getCurrentTime(), event, info_format); \
            fflush(trace_log_file); \
        } \
    } while (0)

// 具体事件的trace宏
#define TRACE_SEND(seq, ack, flag, length) \
    do { \
        char info_buf[256]; \
        snprintf(info_buf, sizeof(info_buf), "seq:%u ack:%u flag:%d length:%d", seq, ack, flag, length); \
        TRACE_LOG("SEND", info_buf); \
    } while (0)

#define TRACE_RECV(seq, ack, flag, length) \
    do { \
        char info_buf[256]; \
        snprintf(info_buf, sizeof(info_buf), "seq:%u ack:%u flag:%d length:%d", seq, ack, flag, length); \
        TRACE_LOG("RECV", info_buf); \
    } while (0)

#define TRACE_CWND(type, size) \
    do { \
        char info_buf[256]; \
        snprintf(info_buf, sizeof(info_buf), "type:%d size:%d", type, size); \
        TRACE_LOG("CWND", info_buf); \
    } while (0)

#define TRACE_RWND(size) \
    do { \
        char info_buf[256]; \
        snprintf(info_buf, sizeof(info_buf), "size:%d", size); \
        TRACE_LOG("RWND", info_buf); \
    } while (0)

#define TRACE_SWND(size) \
    do { \
        char info_buf[256]; \
        snprintf(info_buf, sizeof(info_buf), "size:%d", size); \
        TRACE_LOG("SWND", info_buf); \
    } while (0)

#define TRACE_RTTS(sample_rtt, estimated_rtt, deviation_rtt, timeout_interval) \
    do { \
        char info_buf[256]; \
        snprintf(info_buf, sizeof(info_buf), "SampleRTT:%f EstimatedRTT:%f DeviationRTT:%f TimeoutInterval:%f", \
                 (double)sample_rtt, (double)estimated_rtt, (double)deviation_rtt, (double)timeout_interval); \
        TRACE_LOG("RTTS", info_buf); \
    } while (0)

#define TRACE_DELV(seq, size) \
    do { \
        char info_buf[256]; \
        snprintf(info_buf, sizeof(info_buf), "seq:%u size:%d", seq, size); \
        TRACE_LOG("DELV", info_buf); \
    } while (0)
#else
// 非trace模式下不输出任何trace信息
#define TRACE_LOG(event, info_format, ...) do {} while (0)
#define TRACE_SEND(seq, ack, flag, length) do {} while (0)
#define TRACE_RECV(seq, ack, flag, length) do {} while (0)
#define TRACE_CWND(type, size) do {} while (0)
#define TRACE_RWND(size) do {} while (0)
#define TRACE_SWND(size) do {} while (0)
#define TRACE_RTTS(sample_rtt, estimated_rtt, deviation_rtt, timeout_interval) do {} while (0)
#define TRACE_DELV(seq, size) do {} while (0)
#endif

// 前向声明，解决循环依赖问题
typedef struct tju_packet_s tju_packet_t;
typedef struct nacked_packet_s nacked_packet_t;
typedef struct received_packet_s received_packet_t;

#include "tju_packet.h"

// 环境选择宏 - 注释掉不需要的环境
#define LOCAL_ENV  // 本地测试环境
// #define ONLINE_ENV  // 线上测试环境

// 本地环境IP地址
#ifdef LOCAL_ENV
#define LOCAL_CLIENT_IP "172.17.0.2"
#define LOCAL_SERVER_IP "172.17.0.3"
#endif

// 线上环境IP地址
#ifdef ONLINE_ENV
#define ONLINE_CLIENT_IP "172.17.0.5"
#define ONLINE_SERVER_IP "172.17.0.6"
#endif

// 根据当前环境定义实际使用的IP地址
#ifdef LOCAL_ENV
#define CLIENT_IP LOCAL_CLIENT_IP
#define SERVER_IP LOCAL_SERVER_IP
#elif defined(ONLINE_ENV)
#define CLIENT_IP ONLINE_CLIENT_IP
#define SERVER_IP ONLINE_SERVER_IP
#else
#error "必须定义测试环境：LOCAL_ENV 或 ONLINE_ENV"
#endif

// 单位是byte
#define SIZE64 8
#define SIZE32 4
#define SIZE16 2
#define SIZE8  1

// 一些Flag
#define NO_FLAG 0
#define NO_WAIT 1
#define TRUE 1
#define FALSE 0

// 定义最大包长 防止IP层分片
#define MAX_DLEN 1367 	// 最大包内数据长度
#define MAX_LEN 1400 	// 最大包长度 20字节header 8字节时间戳 1367字节数据 盈余5字节

// TCP socket 状态定义
#define CLOSED 0
#define LISTEN 1
#define SYN_SENT 2
#define SYN_RECV 3
#define ESTABLISHED 4
#define FIN_WAIT_1 5
#define FIN_WAIT_2 6
#define CLOSE_WAIT 7
#define CLOSING 8
#define LAST_ACK 9
#define TIME_WAIT 10
#define STOP_WAIT 11	

// TCP 拥塞控制状态
#define SLOW_START 0
#define CONGESTION_AVOIDANCE 1
#define FAST_RECOVERY 2
#define TIMEOUT 3

// TCP 接受窗口大小
#define TCP_RECVWN_SIZE 32*MAX_DLEN // 比如最多放32个满载数据包

// 超时相关
#define MAX_RETRANSMIT_CNT 5 // 最大重传次数
#define RTO 200 // 默认超时时间 单位是毫秒
#define ALPHA 0.125
#define BETA 0.25
#define MU 1
#define SIGMA 4
#define TIMEWAIT_TIMEOUT 30 // 单位是秒

// 未确认数据包链表相关
typedef struct nacked_packet_s{
	tju_packet_t* pkt;
	int retransmit_cnt;
	struct nacked_packet_s* next;
} nacked_packet_t;

typedef struct {
	uint16_t window_size;
	pthread_cond_t send_window_not_full;
	pthread_cond_t recv_window_not_full;
   	uint32_t base;
   	uint32_t nextseq;
   	uint32_t estimated_rtt;
   	uint32_t dev_rtt;
   	int ack_cnt;
   	struct itimerval timeout;
   	uint16_t rwnd; 
    int congestion_status;
    uint16_t cwnd; 
    uint16_t ssthresh; 
	nacked_packet_t* head;
} sender_window_t;

// TCP 接受窗口
// 注释的内容如果想用就可以用 不想用就删掉 仅仅提供思路和灵感
typedef struct received_packet_s {
	uint32_t seq;
	uint16_t len;
	char* data;
	struct received_packet_s* next;
} received_packet_t;

typedef struct {
	uint16_t window_size;
//	 char received[TCP_RECVWN_SIZE];
   	received_packet_t* head;
//   char buf[TCP_RECVWN_SIZE];
   	uint32_t expect_seq;
} receiver_window_t;

// TCP 窗口 每个建立了连接的TCP都包括发送和接受两个窗口
typedef struct {
	sender_window_t* wnd_send;
  	receiver_window_t* wnd_recv;
} window_t;

typedef struct {
	uint32_t ip;
	uint16_t port;
} tju_sock_addr;


// TJU_TCP 结构体 保存TJU_TCP用到的各种数据
typedef struct {
	int state; // TCP的状态
	pthread_mutex_t state_lock; // 状态锁
	pthread_cond_t state_change; // 状态条件变量

	tju_sock_addr bind_addr; // 存放bind和listen时该socket绑定的IP和端口
	tju_sock_addr established_local_addr; // 存放建立连接后 本机的 IP和端口
	tju_sock_addr established_remote_addr; // 存放建立连接后 连接对方的 IP和端口

	pthread_mutex_t send_lock; // 发送数据锁
	char* sending_buf; // 发送数据缓存区
	int sending_len; // 发送数据缓存长度

	pthread_mutex_t recv_lock; // 接收数据锁
	char* received_buf; // 接收数据缓存区
	int received_len; // 接收数据缓存长度

	pthread_cond_t wait_cond; // 可以被用来唤醒recv函数调用时等待的线程

	window_t window; // 发送和接受窗口

} tju_tcp_t;

#endif